package config

import (
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
	"log"
)

var Conf *Config

// Config 配置
type Config struct {
	Log      LogConf                 `mapstructure:"log"`
	Port     int                     `mapstructure:"port"`
	WsPort   int                     `mapstructure:"wsPort"`
	Metric   MetricConf              `mapstructure:"metric"`
	HttpPort int                     `mapstructure:"httpPort"`
	AppName  string                  `mapstructure:"appName"`
	Database Database                `mapstructure:"db"`
	Jwt      JwtConf                 `mapstructure:"jwt"`
	Grpc     GrpcConf                `mapstructure:"grpc"`
	Etcd     EtcdConf                `mapstructure:"etcd"`
	Domain   map[string]Domain       `mapstructure:"domain"`
	Services map[string]ServicesConf `mapstructure:"services"`
}

// InitConfig 初始化配置
func InitConfig(config string) {
	Conf = new(Config)
	v := viper.New()
	// 设置配置文件路径
	v.SetConfigFile(config)
	// 监听配置文件变动
	watchConfig(v)
	// 读取配置文件
	err := v.ReadInConfig()
	if err != nil {
		panic(fmt.Errorf("读取配置文件出错：%v\n", err))
		return
	}
	// 解析
	err = v.Unmarshal(&Conf)
	if err != nil {
		panic(fmt.Errorf("解析配置文件出错：%v\n", err))
		return
	}
}

// watchConfig 监听配置文件发生变化
func watchConfig(v *viper.Viper) {
	v.WatchConfig()
	v.OnConfigChange(func(in fsnotify.Event) {
		log.Println("配置文件变动，重新加载")
		// 解析
		err := v.Unmarshal(&Conf)
		if err != nil {
			panic(fmt.Errorf("修改后解析配置文件出错：%v\n", err))
			return
		}
	})
}

type ServicesConf struct {
	Id         string `mapstructure:"id"`
	ClientHost string `mapstructure:"clientHost"`
	ClientPort int    `mapstructure:"clientPort"`
}

type Domain struct {
	Name        string `mapstructure:"name"`
	LoadBalance bool   `mapstructure:"loadBalance"`
}

type JwtConf struct {
	Secret string `mapstructure:"secret"`
	Exp    int    `mapstructure:"exp"`
}

type LogConf struct {
	Level string `mapstructure:"level"`
}

// Database 数据库配置
type Database struct {
	MongoConf MongoConf `mapstructure:"mongo"`
	RedisConf RedisConf `mapstructure:"redis"`
}

type MetricConf struct {
	Enable bool `mapstructure:"enable"`
	Port   int  `mapstructure:"port"`
}

// MongoConf MongoDB 配置
type MongoConf struct {
	Url         string `mapstructure:"url"`
	Db          string `mapstructure:"db"`
	UserName    string `mapstructure:"userName"`
	Password    string `mapstructure:"password"`
	MinPoolSize uint64 `mapstructure:"minPoolSize"`
	MaxPoolSize uint64 `mapstructure:"maxPoolSize"`
}

// RedisConf Redis 配置
type RedisConf struct {
	Addr         string   `mapstructure:"addr"`
	ClusterAddrs []string `mapstructure:"clusterAddrs"`
	Password     string   `mapstructure:"password"`
	PoolSize     int      `mapstructure:"poolSize"`
	MinIdleConns int      `mapstructure:"minIdleConns"`
	Host         string   `mapstructure:"host"`
	Port         int      `mapstructure:"port"`
}

// EtcdConf Etcd 配置
type EtcdConf struct {
	Addrs       []string       `mapstructure:"addrs"`
	RWTimeout   int            `mapstructure:"rwTimeout"`
	DialTimeout int            `mapstructure:"dialTimeout"`
	Register    RegisterServer `mapstructure:"register"`
}

type RegisterServer struct {
	Addr         string `mapstructure:"addr"`         // 服务地址
	Name         string `mapstructure:"name"`         // 服务名称
	Version      string `mapstructure:"version"`      // 服务版本号
	Weight       int    `mapstructure:"weight"`       // 服务权重
	KeepAliveTtl int64  `mapstructure:"keepAliveTtl"` //多久进行心跳检测
}

type GrpcConf struct {
	Addr string `mapstructure:"addr"`
}
